/*******************************************************************************
*
*   FILE NAME:
*       Vector2.cpp - Vector2 class implementation
*
*   DESCRIPTION:
*       Defines a vector with two components.
*
*******************************************************************************/
#include "Vector2.h"

#include <math.h>

const Vector2 Vector2::One = Vector2( 1.0f, 1.0f );
const Vector2 Vector2::UnitX = Vector2( 1.0f, 0.0f );
const Vector2 Vector2::UnitY = Vector2( 0.0f, 1.0f );
const Vector2 Vector2::Zero = Vector2( 0.0f, 0.0f );

Vector2::Vector2( void )
    : X( 0.0f ),
      Y( 0.0f )
{
}

Vector2::Vector2( float32 value )
    : X( value ),
      Y( value )
{
}

Vector2::Vector2( float32 x, float32 y )
    : X( x ),
      Y( y )
{
}

Vector2::Vector2( const Vector2& other )
    : X( other.X ),
      Y( other.Y )
{
}

Vector2::~Vector2( void )
{
}

Vector2& Vector2::operator=( const Vector2& other )
{
    X = other.X;
    Y = other.Y;
    return *this;
}

boolean operator==( const Vector2& vec1, const Vector2& vec2 )
{
    return ( vec1.X == vec2.X && vec1.Y == vec2.Y );
}

boolean operator!=( const Vector2& vec1, const Vector2& vec2 )
{
    return ( vec1.X != vec2.X || vec1.Y != vec2.Y );
}

Vector2 operator+( const Vector2& vec1, const Vector2& vec2 )
{
    return Vector2::Add( vec1, vec2 );
}

Vector2 operator-( const Vector2& vec1, const Vector2& vec2 )
{
    return Vector2::Subtract( vec1, vec2 );
}

Vector2 operator*( const Vector2& vec1, const Vector2& vec2 )
{
    return Vector2::Multiply( vec1, vec2 );
}

Vector2 operator*( const Vector2& vec, float32 scalar )
{
    return Vector2::Multiply( vec, scalar );
}

Vector2 operator*( float32 scalar, const Vector2& vec )
{
    return Vector2::Multiply( vec, scalar );
}

Vector2 operator/( const Vector2& vec1, const Vector2& vec2 )
{
    return Vector2::Divide( vec1, vec2 );
}

Vector2 operator/( const Vector2& vec, float32 divider )
{
    return Vector2::Divide( vec, divider );
}

Vector2 operator-( const Vector2& vec )
{
    return Vector2::Negate( vec );
}

Vector2 Vector2::Add( const Vector2& vec1, const Vector2& vec2 )
{
    Vector2 ret;
    Add( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Clamp( const Vector2& vec, const Vector2& min, const Vector2& max )
{
    Vector2 ret;
    Clamp( vec, min, max, ret );
    return ret;
}

float32 Vector2::Distance( const Vector2& vec1, const Vector2& vec2 )
{
    float32 ret;
    Distance( vec1, vec2, ret );
    return ret;
}

float32 Vector2::DistanceSquared( const Vector2& vec1, const Vector2& vec2 )
{
    float32 ret;
    DistanceSquared( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Divide( const Vector2& vec1, const Vector2& vec2 )
{
    Vector2 ret;
    Divide( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Divide( const Vector2& vec, float32 divider )
{
    Vector2 ret;
    Divide( vec, divider, ret );
    return ret;
}

float32 Vector2::Dot( const Vector2& vec1, const Vector2& vec2 )
{
    float32 ret;
    Dot( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Max( const Vector2& vec1, const Vector2& vec2 )
{
    Vector2 ret;
    Max( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Min( const Vector2& vec1, const Vector2& vec2 )
{
    Vector2 ret;
    Min( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Multiply( const Vector2& vec1, const Vector2& vec2 )
{
    Vector2 ret;
    Multiply( vec1, vec2, ret );
    return ret;
}

Vector2 Vector2::Multiply( const Vector2& vec, float32 scalar )
{
    Vector2 ret;
    Multiply( vec, scalar, ret );
    return ret;
}

Vector2 Vector2::Negate( const Vector2& vec )
{
    Vector2 ret;
    Negate( vec, ret );
    return ret;
}

Vector2 Vector2::Normalize( const Vector2& vec )
{
    Vector2 ret;
    Normalize( vec, ret );
    return ret;
}

Vector2 Vector2::Reflect( const Vector2& vec, const Vector2& normal )
{
    Vector2 ret;
    Reflect( vec, normal, ret );
    return ret;
}

Vector2 Vector2::Subtract( const Vector2& vec1, const Vector2& vec2 )
{
    Vector2 ret;
    Subtract( vec1, vec2, ret );
    return ret;
}

void Vector2::Add( const Vector2& vec1, const Vector2& vec2, Vector2& result )
{
    result.X = vec1.X + vec2.X;
    result.Y = vec1.Y + vec2.Y;
}

void Vector2::Clamp( const Vector2& vec, const Vector2& min, const Vector2& max, Vector2& result )
{
    result.X = ( max.X < vec.X ) ? max.X : ( min.X > vec.X ) ? min.X : vec.X;
    result.Y = ( max.Y < vec.Y ) ? max.Y : ( min.Y > vec.Y ) ? min.Y : vec.Y;
}

void Vector2::Distance( const Vector2& vec1, const Vector2& vec2, float32& result )
{
    DistanceSquared( vec1, vec2, result );
    result = sqrt( result );
}

void Vector2::DistanceSquared( const Vector2& vec1, const Vector2& vec2, float32& result )
{
    float32 dx = vec1.X - vec2.X;
    float32 dy = vec1.Y - vec2.Y;
    result = ( dx * dx ) + ( dy * dy );
}

void Vector2::Divide( const Vector2& vec1, const Vector2& vec2, Vector2& result )
{
    result.X = vec1.X / vec2.X;
    result.Y = vec1.Y / vec2.Y;
}

void Vector2::Divide( const Vector2& vec, float32 divider, Vector2& result )
{
    result.X = vec.X / divider;
    result.Y = vec.Y / divider;
}

void Vector2::Dot( const Vector2& vec1, const Vector2& vec2, float32& result )
{
    result = ( vec1.X * vec2.X ) + ( vec1.Y * vec2.Y );
}

void Vector2::Max( const Vector2& vec1, const Vector2& vec2, Vector2& result )
{
    result.X = ( vec1.X > vec2.X ) ? vec1.X : vec2.X;
    result.Y = ( vec1.Y > vec2.Y ) ? vec1.Y : vec2.Y;
}

void Vector2::Min( const Vector2& vec1, const Vector2& vec2, Vector2& result )
{
    result.X = ( vec1.X < vec2.X ) ? vec1.X : vec2.X;
    result.Y = ( vec1.Y < vec2.Y ) ? vec1.Y : vec2.Y;
}

void Vector2::Multiply( const Vector2& vec1, const Vector2& vec2, Vector2& result )
{
    result.X = vec1.X * vec2.X;
    result.Y = vec1.Y * vec2.Y;
}

void Vector2::Multiply( const Vector2& vec, float32 scalar, Vector2& result )
{
    result.X = vec.X * scalar;
    result.Y = vec.Y * scalar;
}

void Vector2::Negate( const Vector2& vec, Vector2& result )
{
    result.X = -vec.X;
    result.Y = -vec.Y;
}

void Vector2::Normalize( const Vector2& vec, Vector2& result )
{
    float32 length = vec.Length();
    result.X = vec.X / length;
    result.Y = vec.Y / length;
}

void Vector2::Reflect( const Vector2& vec, const Vector2& normal, Vector2& result )
{
    //TODO
}

void Vector2::Subtract( const Vector2& vec1, const Vector2& vec2, Vector2& result )
{
    result.X = vec1.X - vec2.X;
    result.Y = vec1.Y - vec2.Y;
}

float32 Vector2::Length( void ) const
{
    return sqrt( LengthSquared() );
}

float32 Vector2::LengthSquared( void ) const
{
    return ( X * X ) + ( Y * Y );
}

void Vector2::Normalize( void )
{
    Normalize( *this, *this );
}
